package com.m1.tzolkin.model.util;

import java.util.ArrayList;
import java.util.Collection;


public class CycleList<E> extends ArrayList<E> implements ICycleList<E> {
	
	// ATTRIBUTS
	
	private static final long serialVersionUID = 1L;
	
	private int current;
	private int first;
	
	// CONTRUCTEUR
	
	public CycleList(Collection<? extends E> items) {
		super(items);
	}
	
	// REQUETES

	@Override
	public E getCurrent() {
		if (super.isEmpty()) {
			return null;
		}
		return get(current);
	}

	@Override
	public E getFirst() {
		if (super.isEmpty()) {
			return null;
		}
		return get(first);
	}

	@Override
	public E getLast() {
		if (super.isEmpty()) {
			return null;
		}
		return get(prev(first));
	}
	
	// COMMANDES

	@Override
	public void incCurrent() {
		if (super.isEmpty()) {
			throw new IllegalStateException();
		}
		current = next(current);
	}

	@Override
	public void setFirst(E e) {
		if (e == null) {
			throw new IllegalArgumentException();
		}
		if (super.isEmpty()) {
			throw new IllegalStateException();
		}
		first = indexOf(e);
	}
	
	@Override
	public void setAleaFirst() {
		if (super.isEmpty()) {
			throw new IllegalStateException();
		}
		first = (int) (Math.random() * size());
	}

	@Override
	public void setFirstToCurrent() {
		if (super.isEmpty()) {
			throw new IllegalStateException();
		}
		current = first;
	}

	@Override
	public void setFirstToNeighbour() {
		if (super.isEmpty()) {
			throw new IllegalStateException();
		}
		first = next(first);
	}
	
	// OUTILS
	
	/**
	 * Retourne le modulo positif de x et n.
	 */
	private static int mod(int x, int n) {
		int r = x % n;
		return (r < 0) ? r + n : r;
	}
	
	/**
	 * Retourne l'indice suivant n dans la liste des joueurs.
	 */
	private int next(int n) {
		return mod(n + 1, size());
	}
	
	/**
	 * Retourne l'indice pr�c�dant n dans la liste des joueurs.
	 */
	private int prev(int n) {
		return mod(n - 1, size());
	}

}
